﻿//-----------------------------------------------------------------------
// <copyright file="StreamWrapper.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
// </copyright>
// <author>Yogesh M Joshi</author>
// <email>ymjoshi@live.com</email>
// <date>16-May-2011</date>
//-----------------------------------------------------------------------

namespace SmartTag.Common.IFilter
{
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.ComTypes;

    /// <summary>
    /// This class is wrapper over the IStream com Object
    /// </summary>
    public class StreamWrapper : IStream
    {
        #region "Private Fields"

        /// <summary>
        /// Stream object
        /// </summary>
        private Stream stream;

        #endregion

        /// <summary>
        /// Initializes a new instance of the StreamWrapper class
        /// </summary>
        /// <param name="stream">Stream to wrap</param>
        public StreamWrapper(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("StreamWrapper", "Stream to wrap can not be null.");
            }

            this.stream = stream;
        }

        /// <summary>
        /// Clones the current stream
        /// This function is not implemented
        /// </summary>
        /// <param name="clone">Cloned stream</param>
        public void Clone(out IStream clone)
        {
            clone = null;
        }

        /// <summary>
        /// Commits the operations on given stream
        /// This function is not implemented
        /// </summary>
        /// <param name="flags">Commit flags</param>
        public void Commit(int flags)
        {
        }

        /// <summary>
        /// Copies current stream content to other stream
        /// This function is not implemented
        /// </summary>
        /// <param name="stream">Destination stream</param>
        /// <param name="byteCount">Bytes to copy</param>
        /// <param name="bytesRead">Number of bytes read</param>
        /// <param name="bytesCopied">Number of bytes copied</param>
        public void CopyTo(IStream stream, long byteCount, System.IntPtr bytesRead, System.IntPtr bytesCopied)
        {
        }

        /// <summary>
        /// Locks the given region on stream
        /// This function is not implemented
        /// </summary>
        /// <param name="offset">Offset in stream</param>
        /// <param name="byteCount">Number of bytes to lock</param>
        /// <param name="lockType">Type of the lock</param>
        public void LockRegion(long offset, long byteCount, int lockType)
        {
        }

        /// <summary>
        /// Reads specified number of bytes from stream
        /// </summary>
        /// <param name="buffer">Byte buffer</param>
        /// <param name="bufferLength">Length of buffer</param>
        /// <param name="bytesRead">Number of bytes read</param>
        public void Read(byte[] buffer, int bufferLength, System.IntPtr bytesRead)
        {
            Marshal.WriteInt64(bytesRead, (long)this.stream.Read(buffer, 0, bufferLength));
        }

        /// <summary>
        /// Revert stream to its original state
        /// This function is not implemented
        /// </summary>
        public void Revert()
        {
        }

        /// <summary>
        /// Seek inside stream
        /// </summary>
        /// <param name="count">Number of bytes to seek</param>
        /// <param name="origin">Seek origin</param>
        /// <param name="newPosition">New positon after seek opertaion</param>
        public void Seek(long count, int origin, System.IntPtr newPosition)
        {
            long pos = this.stream.Seek(count, (SeekOrigin)origin);

            if (newPosition != IntPtr.Zero)
            {
                Marshal.WriteInt64(newPosition, pos);
            }
        }

        /// <summary>
        /// Set the size of stream
        /// This function is not implemented
        /// </summary>
        /// <param name="newSize">New size of stream</param>
        public void SetSize(long newSize)
        {
        }

        /// <summary>
        /// Get the current stream status
        /// </summary>
        /// <param name="streamStatus">Structure containing stream status information</param>
        /// <param name="statusFlag">Status flag</param>
        public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG streamStatus, int statusFlag)
        {
            streamStatus = new System.Runtime.InteropServices.ComTypes.STATSTG();
            
            // Set storage type = Stream
            streamStatus.type = 2;

            // Set size of the stream
            streamStatus.cbSize = this.stream.Length;

            // Lock mode LOCK_EXCLUSIVE
            streamStatus.grfLocksSupported = 2;
        }

        /// <summary>
        /// Unlock specific region on stream
        /// This function is not implemented
        /// </summary>
        /// <param name="offset">Offset inside stream</param>
        /// <param name="byteCount">Total number of bytes</param>
        /// <param name="lockType">Type of the lock</param>
        public void UnlockRegion(long offset, long byteCount, int lockType)
        {
        }

        /// <summary>
        /// Write given bytes on stream
        /// This function is not implemented
        /// </summary>
        /// <param name="buffer">Buffer to write</param>
        /// <param name="bufferLength">Lenght of buffer</param>
        /// <param name="bytesWritten">Total number of bytes written</param>
        public void Write(byte[] buffer, int bufferLength, System.IntPtr bytesWritten)
        {
        }
    }
}
